Skip to content

community: add speckit-inventory extension and inventory-alignment preset for #4164 - #4220

Closed
Yash-Chindam wants to merge 1 commit into
github:mainfrom
Yash-Chindam:community/4164-add-inventory-alignment
Closed

community: add speckit-inventory extension and inventory-alignment preset for #4164#4220
Yash-Chindam wants to merge 1 commit into
github:mainfrom
Yash-Chindam:community/4164-add-inventory-alignment

Conversation

@Yash-Chindam

@Yash-Chindam Yash-Chindam commented Aug 20, 2026

Copy link
Copy Markdown

Description

Lists a paired community extension and preset that deliver Phase 1 of #4164 without any change to Spec Kit core, following the design @mnriem proposed in that issue. Per CONTRIBUTING's note on large changes, that comment is the prior maintainer agreement for this direction.

The problem this solves

A user reworks a UI requirement mid-feature. The agent looks for related work by grepping similar wording across spec.md, plan.md, and tasks.md. After the reword — "charge on Pay" becomes "show a confirm modal" — nothing matches, so the agent adds a second live requirement instead of updating the first. /speckit.analyze cannot catch it, because the contradicting line was never loaded into context. The user is left with duplicate and contradictory requirements to reconcile by hand.

The fix is to stop discovering requirements by wording and start discovering them by ID: derive the complete set of live IDs from the artifacts that already exist, then make the agent classify every proposed requirement against that set before it writes.

What is being listed

Both ship from one standalone repo, spec-kit-inventory-alignment, at v0.1.0.

speckit-inventory — extension, category visibility, effect read-only:

  • Regenerates every live FR-/NFR-/SC-/AC-/T- ID from the existing spec.md and tasks.md on each run and prints JSON. Nothing is persisted, so a tasks.yaml to tasks.md sync problem cannot arise — there is no second source of truth to drift.
  • speckit.speckit-inventory.list returns the complete inventory; speckit.speckit-inventory.context returns a focused context pack (one task plus only the requirements it covers) instead of a whole-file dump.
  • Optional before_specify and before_analyze hooks, both optional: true so they prompt rather than fire automatically.

inventory-alignment — preset:

  • wrap overrides of speckit.specify and speckit.analyze using the {CORE_TEMPLATE} placeholder, prepending a pre-pass that classifies each proposed requirement as already-true / edit-existing / conflict / genuinely-new, then falling through to the original command body.
  • append override of tasks-template documenting the optional covers: field that links a task to the requirement IDs it implements.

Design constraints held deliberately

  • No second source of truth — the inventory is derived, never stored.
  • No mutation — the extension only reads; there are no write calls in the script.
  • No core changes — this PR touches only catalog and docs files.
  • No embeddings — that was Phase 2 in the original proposal and is out of scope.

One naming deviation, flagged deliberately

The issue comment asks for speckit.inv.context, but that name cannot coexist with the extension id speckit-inventory the same comment specifies. The extension loader requires a command's namespace segment to equal the manifest id, so that combination fails at install:

Validation Error: Command 'speckit.inv.context' must use extension namespace 'speckit-inventory'

I kept the id and named the commands speckit.speckit-inventory.list / .context. If the shorter invocation is preferred, renaming the extension id to inv gets there — happy to do that instead; it is a one-line manifest change plus new release assets.

Known gap, not blocking

preset.yml's requires: can only declare speckit_version, so the preset cannot formally require the extension. The wrappers degrade safely — without the extension the core workflow runs unchanged — and the pairing is documented in both READMEs. Happy to leave the requires: extensions: enhancement as its own issue, as @mnriem suggested.

Testing

Verified against the published release archives

Not just a local checkout — these ran against the actual download_urls in the catalog entries.

Check Result
specify extension add --from <release url> Installs; both commands registered; 2 agent skills auto-registered
specify preset add --from <release url> Installs at priority 10
specify preset resolve tasks-template Chain resolves 1. [base] core then 2. [append] inventory-alignment v0.1.0
wrap composition Pre-pass precedes the full core body (355 / 271 lines); zero unresolved {CORE_TEMPLATE}; core frontmatter scripts: preserved in speckit.analyze
Hook registration Both written to .specify/extensions.yml as optional: true
Release asset integrity Both URLs return 200; downloaded bytes match the sha256 in the catalog entries
Extension unit tests 9/9 pass

Worked example

Given a spec.md defining FR-001, FR-002, NFR-001, SC-001, and a tasks.md whose T010 covers SC-001 and a nonexistent FR-009, the inventory reports the dangling reference by source rather than silently accepting it:

{ "id": "FR-009", "source": "tasks.md", "line": 6,
  "text": "- [ ] T010 [US2] Add retry telemetry in src/telemetry/ (covers: SC-001, FR-009)" }

spec.md is scanned first, so it wins as the definition site; anything whose source is tasks.md is a reference to a requirement that was never defined. The speckit.analyze pre-pass instructs the agent to report exactly that case.

The context pack returns only the requirements a given task covers, not the whole spec — which is the token-cost argument for the approach:

--task T002  ->  task T002 plus FR-001, NFR-001   (2 of 5 requirements)
--task T001  ->  task T001 plus nothing           (unlinked setup task, valid)

Spec Kit's own suite

630 passed for catalog- and community-selected tests on this branch. Two failures are WinError 1314 symlink-privilege failures from my Windows environment; they reproduce identically with these changes stashed, so they are unrelated to this PR.

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

What was not tested

Command composition and registration are verified above, but /speckit.specify and /speckit.analyze were not run end-to-end inside a coding agent to observe the pre-pass and hook prompt in a live session. This PR changes no core command behavior, so I read CONTRIBUTING's manual-testing requirement as not applying to it — but the matrix is written and I will run it and post results if a maintainer wants that evidence before merge.

My own analysis of the developer experience

Honest assessment, including where I think this is weak.

What works well. The read-only, derive-every-time design is the part I would defend hardest. The original issue proposed YAML sidecars, and working through it convinced me that would have been a mistake — a sidecar makes the sync problem the user's problem, and the sync problem is worse than the bug being fixed. Deriving on every run means the inventory is never stale and there is nothing to migrate for existing projects, which also answers the migration question I raised earlier in the issue.

What is genuinely uncertain. The value depends on the agent actually honoring the pre-pass. The extension guarantees the data is complete and cheap to load; it cannot guarantee the model classifies correctly against it. I expect this to reduce duplicate requirements substantially rather than eliminate them, and I would rather say that plainly than oversell it. The covers: field is likewise only as good as the agent's discipline in emitting it — the append override documents it, but nothing enforces it, and a task without covers: degrades to an empty context pack.

The rough edge users will hit first. The two-part install is awkward. Because preset.yml cannot declare an extension dependency, a user who installs only the preset gets prompts that silently do nothing — the workflow still runs correctly, but the feature appears broken. Both READMEs lead with this, and it is the strongest argument for the requires: extensions: enhancement being worth doing.

Scope I deliberately did not take. Embeddings would help with genuine paraphrase matching, which is the harder half of the original problem. Leaving them out keeps this dependency-free and reviewable, and I would rather see whether the ID-based half earns adoption first.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Filed by @Yash-Chindam. Substantial AI assistance — code generation, not just documentation or comments — in two distinct passes.

Pass 1 — ChatGPT (Codex, model: GPT-5). Drafted the initial extension, preset, and tests in a separate repository, and wrote my earlier scoping comment on #4164.

Pass 2 — Claude Code (model: Claude Opus 5), autonomous. Reviewed that draft against this issue thread and the repo's own guidance, and found real defects in it:

  • The append override of tasks-template and the before_specify / before_analyze hooks from @mnriem's comment were missing entirely. The covers: field was load-bearing for the extension, but nothing taught the template to emit it.
  • Requirement IDs were harvested from spec.md only, rather than from spec.md and tasks.md, so dangling references were invisible.
  • The CLI rejected unpadded task IDs — --task T14 failed on a task literally written as T14, because the parser normalized to T014 but the lookup did not.

It fixed those, added the list command, expanded the tests from 2 to 9, produced these catalog entries and documentation rows, and wrote this description.

Attribution of the testing above, stated precisely. Every check in the Testing section was executed by Claude Code on my machine at my direction, and I have reviewed the results. I am not claiming I re-ran each command by hand. Per AGENTS.md, the commit on this branch carries an Assisted-by: Claude Code (model: Claude Opus 5, autonomous) trailer, and I will disclose agent involvement again in each review-round comment rather than relying on this section to cover them.

This account had no other open pull requests in this repository when this one was filed.

One process note

add-community-extension.md and add-community-preset.md automate these catalogs from [Extension]: / [Preset]: issue submissions, and EXTENSION-PUBLISHING-GUIDE.md says not to open a pull request that edits extensions/catalog.community.json directly. I raised this as a PR because that is what the issue asked for — very happy to close it and refile through the two issue templates if you prefer the automated path.

@Yash-Chindam
Yash-Chindam requested a review from mnriem as a code owner August 20, 2026 11:53
…eset

Lists the paired read-only inventory extension and alignment preset built for
issue github#4164, following the extension + preset design a maintainer proposed
there. Both ship from a standalone repo, so Spec Kit core is unchanged.

Extension (speckit-inventory, read-only): regenerates every live FR-/NFR-/SC-/
AC-/T- ID from the existing spec.md and tasks.md on each run and prints JSON.
Nothing is persisted, so no second source of truth can drift.

Preset (inventory-alignment): wraps speckit.specify and speckit.analyze with a
classify-against-the-inventory pre-pass and appends the optional covers: field
to tasks-template.

The listed extension and preset were first drafted with ChatGPT (Codex, GPT-5)
in a separate repository. The catalog entries and documentation rows in this
commit were authored by Claude Code, which also reviewed that draft and
corrected defects in it before release.

Assisted-by: Claude Code (model: Claude Opus 5, autonomous)
@Yash-Chindam
Yash-Chindam force-pushed the community/4164-add-inventory-alignment branch from b19f280 to d5030b2 Compare August 20, 2026 12:28
@mnriem

mnriem commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

@Yash-Chindam Can you please file 2 separate issues, one for the extension submission and one for the preset submission. We have issue template for these that run agentic workflows that vet the submissions. Thanks! Great work :)

@Yash-Chindam

Copy link
Copy Markdown
Author

Filed both submissions:

Closing this PR, since the two workflows open their own PRs against the same four files and theirs carry the Closes reference to the submission issues.

Both issues are unlabeled. The template's needs-triage label doesn't exist in the repo so creation with labels failed, and I deliberately didn't apply extension-submission / preset-submission myself since that label is the vetting gate — they'll need a maintainer to trigger the workflows.

One change to the submitted artifacts while preparing these, in Yash-Chindam/spec-kit-inventory-alignment@312f1a3: both READMEs now document the specify extension add --from <download-url> / specify preset add --from <download-url> install form rather than only --dev, which is what the preset submission checklist asks for. The Documentation URLs in both issues point at main to reflect that. Release assets and their hashes are unchanged from v0.1.0.

Also flagged in #4226, since it's a deviation from your comment rather than something I'd want discovered during vetting: speckit.inv.context can't coexist with the extension id speckit-inventory, because the loader requires a command's namespace segment to equal the manifest id — installing that pairing fails with Command 'speckit.inv.context' must use extension namespace 'speckit-inventory'. I kept the id and used speckit.speckit-inventory.list / .context. If you'd prefer the shorter invocation, renaming the extension id to inv gets there in one manifest line plus new assets.

Disclosure: this comment and the two submissions were written by Claude Code (model: Claude Opus 5), acting autonomously on behalf of @Yash-Chindam. Repository commits carry Assisted-by: trailers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants